﻿#include <iostream>
#include <iomanip> // 引入std::setw (可以指定输出数据的宽度)
#include <stdint.h> //固定宽度整数类型头文件

int main()
{
	std::cout << "Hello World!\n";

	//基本数据类型
	float a = 3.45;
	double b = a;
	long c = 99999999;
	long double ld = 9.0909090;
	bool d = false;
	char e = 'e';
	char16_t f = 'h';
	short int g = 99;
	int  h = 99;
	long int  i = 99;
	long long int j = 99;

	std::nullptr_t np;

	//输出各类型的值和占用的bit大小
	std::cout << a << "占用bit=" << sizeof(a) << "\n";
	std::cout << b << "占用bit=" << sizeof(b) << "\n";
	std::cout << c << "占用bit=" << sizeof(c) << "\n";
	std::cout << ld << "占用bit=" << sizeof(ld) << "\n";
	std::cout << d << "占用bit=" << sizeof(d) << "\n";
	std::cout << e << "占用bit=" << sizeof(e) << "\n";
	std::cout << f << "占用bit=" << sizeof(f) << "\n";
	std::cout << g << "占用bit=" << sizeof(g) << "\n";
	std::cout << h << "占用bit=" << sizeof(h) << "\n";
	std::cout << i << "占用bit=" << sizeof(i) << "\n";
	std::cout << j << "占用bit=" << sizeof(j) << "\n";
	std::cout << "空指针类型占用bit=" << sizeof(np) << "\n";

	//和上面的代码等效
	std::cout << std::left; // 左对齐
	std::cout << std::setw(16) << "bool:" << sizeof(bool) << " bytes\n";
	std::cout << std::setw(16) << "char:" << sizeof(char) << " bytes\n";
	std::cout << std::setw(16) << "short:" << sizeof(short) << " bytes\n";
	std::cout << std::setw(16) << "int:" << sizeof(int) << " bytes\n";
	std::cout << std::setw(16) << "long:" << sizeof(long) << " bytes\n";
	std::cout << std::setw(16) << "long long:" << sizeof(long long) << " bytes\n";
	std::cout << std::setw(16) << "float:" << sizeof(float) << " bytes\n";
	std::cout << std::setw(16) << "double:" << sizeof(double) << " bytes\n";
	std::cout << std::setw(16) << "long double:" << sizeof(long double) << " bytes\n";


	//有符号类型和无符号类型的区别：
	//有符号类型用signed修饰，默认就是有符号类型，可以不用写signed关键字，
	//有符号类型用unsigned修饰，尽量避免用无符号类型

	unsigned short us = 100;
	unsigned int ui = 100;
	unsigned long ul = 2;
	unsigned long long ull = 2;

	//如果数学运算（例如算术或比较）有一个有符号整数和一个无符号整数，
	// 则有符号整数通常会转换为无符号整数。因此，结果将是无符号的。
	auto sum = h - us;
	std::cout << "有符号整数和一个无符号整数=" << sum << "\n";

	//int类型会根据不通的计算机改变其大小，
	//演示使用固定宽度的类型使用
	std::int8_t aa;//	一字节有符号 - 128 to 127
	std::uint8_t bb;//	一字节无符号	0 to 255
	std::int16_t cc;//	两字节有符号 - 32, 768 to 32, 767
	std::uint16_t dd;//	两字节无符号	0 to 65, 535
	std::int32_t	ee;// 四字节有符号 - 2, 147, 483, 648 to 2, 147, 483, 647
	std::uint32_t	ff;// 四字节无符号	0 to 4, 294, 967, 295
	std::int64_t	gg;// 八字节有符号 - 9, 223, 372, 036, 854, 775, 808 to 9, 223, 372, 036, 854, 775, 807
	std::uint64_t	hh;// 八字节无符号	0 to 18, 446, 744, 073, 709, 551, 615

	//打印字节大小
	std::cout << "int8_t:" << sizeof(int8_t) << "		int8_t\n";
	std::cout << "uint8_t:" << sizeof(uint8_t) << "		uint8_t\n";
	std::cout << "int16_t:" << sizeof(int16_t) << "		int16_t\n";
	std::cout << "uint16_t:" << sizeof(uint16_t) << "	uint16_t\n";
	std::cout << "int32_t:" << sizeof(int32_t) << "		int32_t\n";
	std::cout << "uint32_t:" << sizeof(uint32_t) << "	uint32_t\n";
	std::cout << "int64_t:" << sizeof(int64_t) << "		int64_t\n";
	std::cout << "uint64_t:" << sizeof(uint64_t) << "	uint64_t\n";

	//打印sizeof返回类型的长度
	std::cout << sizeof(std::size_t) << '\n';

	//科学计数法
	long long zs = 5.9736e24; //地球的质量
	long double dz = 9.1093822e-31; //电子的质量

	std::cout << "地球的质量=" << zs << '\n';
	std::cout << "电子的质量=" << dz << '\n';

	//处理小数
	std::cout << std::setprecision(17); // 输出时，精度保留17位
	std::cout << 3.33333333333333333333333333333333333333f << '\n'; // f 意味着 float 类型
	std::cout << 3.33333333333333333333333333333333333333 << '\n'; // 没有后缀意味着 double 类型


	//二进制保存小数是无限接近表示的，赋值0.1，实际输出可能是0.10000000000000001
	double ddd{ 0.1 };
	std::cout << ddd << '\n'; // 使用默认输出精度 6
	std::cout << std::setprecision(17);
	std::cout << ddd << '\n';


	//NaN和Inf
	//第一个是Inf，它表示无穷大。Inf可以是正的，也可以是负的。
	// 第二个是NaN，它代表“不是数字”
	double zero{ 0.0 };
	double posinf{ 5.0 / zero }; // 正无穷
	std::cout << posinf << '\n';

	double neginf{ -5.0 / zero }; // 负无穷
	std::cout << neginf << '\n';

	double nan{ zero / zero }; // 不是数字
	std::cout << nan << '\n';


	/*关于浮点数，应该记住三件事：
	浮点数通常用来存储带有分数，或者非常大或者非常小的数字。
	浮点数通常有小的舍入误差，即使数字的有效位小于精度。大部分情况下，误差比较小，或者输出截断，难以注意到误差。但是比较浮点数的时候，误差就会比较明显。
	在浮点数上执行算数运算会导致误差累积变大。*/

	//打印bool值
	std::cout << "false=" << false << '\n'; //打印0
	std::cout << "true=" << true << '\n'; //打印1

	//如果希望std::cout打印“true”或“false”，而不是0或1，则可以使用std::boolalpha。
	std::cout << std::boolalpha; // 以  true ， false 格式打印bool
	std::cout << "false=" << false << '\n'; //打印false
	std::cout << "true=" << true << '\n'; //打印true

	//整数转换为布尔值
	bool b1 = 4; // 拷贝初始化允许隐式的将 int 转成 bool
	std::cout << b1 << '\n';
	bool b2 = 0; // 拷贝初始化允许隐式的将 int 转成 bool
	std::cout << b2 << '\n';


	bool bbbbb{};
	std::cout << "Enter a boolean value: ";
	// 允许用户输入 'true' or 'false' 作为bool变量的值
	// 大小写敏感, True or TRUE 都不行
	std::cin >> std::boolalpha;
	std::cin >> bbbbb;
	std::cout << "You entered: " << bbbbb << '\n';


	//if 语句
	if (bbbbb) std::cout << "true" << '\n';
	else  std::cout << "false" << '\n';


	//打印字符 注意不要将字符与整数混淆。以下两个初始化不相同：
	char ch{ 5 }; // 使用数字 5 (存储为 5)
	char ch2{ '5' }; // 使用字符 '5' (存储为 53)
	std::cout << ch << '\n';
	std::cout << ch2 << '\n';

	std::cout << "从键盘输入一个字符: ";
	char input_ch{};
	std::cin >> input_ch;
	std::cout << "You entered: " << input_ch << '\n';




	//	//转义字符
	//	所有转义序列的表：
	//
	//		名称						符号	含义
	//		告警（Alert）				\a		发出告警，例如响铃
	//		退格（Backspace）			\b		将光标往后移一格
	//		换页（Formfeed）			\f		将光标移动到下一页
	//		换行（Newline）				\n		将光标移动到下一行
	//		回车（Carriage return）		\r		将光标移动到行的开头
	//		水平制表（Horizontal tab）	\t		水平制表符
	//		垂直制表（Vertical tab）	\v		垂直制表符
	//		单引号（Single quote）		\’		单引号
	//		双引号（Double quote）		\"		双引号
	//		反斜杠（Backslash）			\\		反斜杠
	//		问号（Question mark）		\ ?		问号
	//		八进制数字（Octal number）	\(number)按八进制解释为数字
	// 	十六进制数字（Hex number）	\x(number)	按十六进制解释为数字




		//隐式类型转换
	double aaaaa = a; //自动把float转为double
	aaaaa = 9.999;
	//强制转换
	int castInt = static_cast<int>(aaaaa); //double强制转换为int,会损失精度

	std::cout << "aaaaa: " << aaaaa << '\n';
	std::cout << "castInt: " << castInt << '\n';

}
